export enum TokenStatus {
    expire = 'expire',              // 登录已经过期
    not = 'not',                    // 没有登录过
    signed = 'signed',              // 已经登录
}

export interface TokenService {
    appName: string,
    update: (username: string, expires: number, token: string) => void,
    getStatus: () => TokenStatus,
    getToken: () => string | null,
    clear: () => void,
    refreshExpires: () => void,
}

/**
 * 创建一个Token管理器
 * @author  韦胜健
 * @date    2021/2/22 15:13
 * @param   appName             应用名称，比如CRM，DMS，STORM，LIVE
 * @param   authKey             请求头headers中用来放token的请求头属性名
 */
export function createTokenService(appName: string, authKey = 'Authorization'): TokenService {

    const getStorageKey = (() => {
        const username = (appName: string) => `${appName}_USERNAME`
        const expire = (appName: string, username: string) => `${appName}_${username}_EXPIRES`
        const expireTimeStamp = (appName: string, username: string) => `${appName}_${username}_EXPIRES_TIME_STAMP`
        const token = (appName: string, username: string) => `${appName}_${username}_TOKEN`
        return {username, expire, expireTimeStamp, token}
    })();

    const state = (() => {
        let username: string | null = window.localStorage.getItem(getStorageKey.username((appName)))
        let expiresTimeStamp: string | null = !username ? null : window.localStorage.getItem(getStorageKey.expireTimeStamp(appName, username))
        let expire: string | null = !username ? null : window.localStorage.getItem(getStorageKey.expire(appName, username))
        let token: string | null = !username ? null : window.localStorage.getItem(getStorageKey.token(appName, username))
        return {
            /*当前用户名*/
            username,
            /*登录有效时长*/
            expire,
            /*登录过期时间*/
            expiresTimeStamp,
            /*登录的token*/
            token,
        }
    })();
    /**
     * 更新token信息
     * @author  韦胜健
     * @date    2021/2/23 11:22
     */
    const update = (username: string, expires: number, token: string): void => {
        // expires = 10 * 1000  // 测试登录过期时间为10s
        window.localStorage.setItem(getStorageKey.username(appName), state.username = username)
        window.localStorage.setItem(getStorageKey.expire(appName, username), state.expire = String(expires))
        window.localStorage.setItem(getStorageKey.expireTimeStamp(appName, username), state.expiresTimeStamp = String(expires + Date.now()))
        window.localStorage.setItem(getStorageKey.token(appName, username), state.token = token)
    }
    /**
     * 获取当前的登录状态
     * @author  韦胜健
     * @date    2021/2/23 11:23
     */
    const getStatus = (): TokenStatus => {
        /*只要用户名、token过期时间以及token三者任意一个不存在，视为没有登录*/
        if (!state.username || !state.expiresTimeStamp || !state.token) {
            return TokenStatus.not
        }
        /*token已经过期*/
        if (!state.expire || Date.now() > Number(state.expiresTimeStamp)) {
            return TokenStatus.expire
        }
        /*正常，已经登录的状态*/
        return TokenStatus.signed
    }
    /**
     * 获取Token
     * @author  韦胜健
     * @date    2021/2/23 11:24
     */
    const getToken = (): null | string => {
        const status = getStatus()
        return status !== TokenStatus.signed ? null : state.token!
    }
    /**
     * 清理token信息
     * @author  韦胜健
     * @date    2021/2/23 11:24
     */
    const clear = () => {
        if (!!state.username) {
            window.localStorage.removeItem(getStorageKey.username(appName))
            window.localStorage.removeItem(getStorageKey.expire(appName, state.username))
            window.localStorage.removeItem(getStorageKey.expireTimeStamp(appName, state.username))
            window.localStorage.removeItem(getStorageKey.token(appName, state.username))
            state.username = null
            state.expiresTimeStamp = null
            state.expire = null
            state.token = null
        }
    }
    const refreshExpires = () => {
        const {username, expire} = state
        if (!!username && !!expire) {
            state.expiresTimeStamp = String(Number(expire) + Date.now())
            window.localStorage.setItem(getStorageKey.expireTimeStamp(appName, username), state.expiresTimeStamp)
        }
    }

    return {
        appName, update, getStatus, getToken, clear, refreshExpires,
    }
}